package com.csdemos.algs;

/**
 * This class represents a single-linked list of Strings.
 * The only data member the class contains is the head of the list. 
 */
public class List {
    /**
     * This class represents the Node of the List.
     * The Node contains the data (of type String) and points to next element (Node).
     */
    public static class Node {
        /**
         * The Node data.
         */ 
        private final String data;
        /**
         * Link to the next Node.
         */ 
        private Node next;
        /**
         * Constructor for Node.
         * @param data The data the Node holds
         * @param next The next Node in the list
	 * @throws NullPointerException if data is null
         */
        public Node(String data, Node next){
	    if(data==null) throw new NullPointerException("data");
            this.data = data;
            this.next = next;
        }
        /**
         * Returns the Node this Node is pointing to.
         * @return The Node this node is pointing to
         */
        public Node getNext(){
            return next;
        }
        /**
         * Returns the data of this Node.
         * @return The data 
         */
        public String getData(){
            return data;
        }
        /**
         * Sets the Node that will follow this Node to the one given in the parameter.
         * @param next the Node that will now follow this Node
         */
        public void setNext(Node next){
            this.next = next;
        }

        @Override
        public String toString() {
            return super.toString() + ": " + data;
        }
        
        
    }
    /**
     * Link to the head Node.
     */ 
    Node head;
    /**
     * Default constructor. Constructs an empty list.
     */
    public List(){
        head = null;
    }
    /**
     * Copy constructor.
     * Returns a copy of a given list. 
     * All nodes of the new list are new nodes, which are copies of the nodes of the given list.
     * The data in the nodes of the resulting list is equal to the data in the nodes of the original list, 
     * i.e., the data of the first node (head) of both lists is equal, 
     * the data of the second node of both lists is equal, etc.
     * The resulting list does not share any nodes with the original list. 
     * @param other The list to be copied
     * @throws NullPointerException if other is null
     */
    public List(List other){
	if(other==null) throw new NullPointerException("other");
        if(other.head == null) {
            return;
        }
        head = new Node(other.head.data, null);
        Node orig = other.head;
        Node copy = head;
        while(orig.next != null) {
            copy.next = new Node(orig.next.data, null);
            orig = orig.next;
            copy = copy.next;
        }
    }
    /**
     * Adds a data item to the beginning of the list.
     * @param data the data item to add
     * @throws NullPointerException if data is null
     */
    public void addFirst(String data){
		if (data==null) {
			throw new NullPointerException("data");
		}
        head = new Node(data, head);
    }
    /**
     * Removes the first node from the list and return its data or null if the list is empty.
     * @return The data of the removed node or null if the list is empty
     */
    public String removeFirst(){
        if (head == null) {
            return null;
        }
        String res = head.data;
        head = head.next;
        return res;
    }
    /**
     * Returns a string representation of the list. The representation has the list
     * elements between "[]", separated by commas. For example, if the list contains the
     * elements "Dan", "Ran", "Ann", and "Zan", the String representation would be "[Dan,Ran,Ann,Zan]".
     * @return A string representation of the list
     */
    public String toString(){
        StringBuilder ans = new StringBuilder("[");
        Node tmp = head;
        while (tmp != null){
            ans.append(tmp.data);
            tmp = tmp.next;
            if (tmp != null)
                ans.append(",");
        }
        ans.append("]");
        return ans.toString();
    }
    
}


